home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
BUSINESS
/
XLMATH22.ZIP
/
SOURCE.ZIP
/
XLUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-10
|
27KB
|
1,045 lines
/*******************************************************************
XLUTIL.C
==========
Author & Copyright:
Roy Kari
Dept. of Chemistry
Laurentian University
Sudbury, Ont.
Canada P3E 2C6
(705) 675-1151
Internet: "ROY@NICKEL.LAURENTIAN.CA"
This module contains all of the memory management routines for
Standalone DLL's. Optionally, the memory management is done with the aid
of the SMARTHEAP memory manager (c) Applegate Software (206)868-8512.
This module also contains pascal string routines and Excel reference
manipulation rotuines.
***************************************************************** */
/* --------------------------< Include files >--------------------- */
#define WIN31
#define _MSC_VER 800
#include <windows.h>
#include <xlcall.h>
#include <stdlib.h>
#include <framewrk.h>
/*----------------------------------------------------------------------*\
You can use both XLAUTO and XLUTIL as general purpose modules
to be included in all of your XLL's. A few modifications are required
but these are easily handles by logical conditionals such as those
shown below.
\*----------------------------------------------------------------------*/
#ifdef _XLMATH
#include "xlmath.h"
#endif
#ifdef _XLMARK
#include "xlmark.h"
#endif
#ifdef _XLQC
#include "xlqc.h"
#endif
#include "xlutil.h"
/*----------------------------------------------------------------------*\
Memory Utilities
When I began this project, "real" mode windows was still a reality.
This meant that memory use was a "real" problem. The only way to
get by the problem was to use a memory allocator such as SMARTHEAP.
Today, with Windows 3.1 and finally Microsoft C/C++ 7, one can
go back to the "old fashioned way" of allocating memory - using
the large model compiler and malloc() and free(). SMARTHEAP still
provides memory debugging techniques superior to standard C but not
superior to C++.
My problem is that I wrote this mess with "real" mode in mind and
compiled it with casts to near and far pointers. I can easily
change to use old fashioned memory allocations but I cannot easily
change to the large model. Hence, what follows is a hybrid. In your
own usage, I suggest thast you forget about near and far data pointers
and let the comiler sort it out.
\*----------------------------------------------------------------------*/
/********************************************************************
GetMem()
=============
This function allocates memory for temporary storage
********************************************************************/
LPVOID PASCAL GetMem(WORD wBytes)
{
LPVOID lpPtr;
if (wBytes > 0)
{
lpPtr = (LPVOID)MemAllocPtr(gScratchPool, wBytes, TRUE);
if (lpPtr == NULL)
ErrorHandler(XLU_NO_MEMORY);
}
else
{
lpPtr = NULL;
ErrorHandler(XLU_MEMORY_ERROR);
}
return (lpPtr);
}
/********************************************************************
FreeMem()
=============
This function de-allocates memory previously allocated in GetMem()
********************************************************************/
void PASCAL FreeMem(LPVOID lpPtr)
{
if ((MemFreePtr((LPVOID)lpPtr) == FALSE))
ErrorHandler(XLU_MEMORY_ERROR);
lpPtr = NULL;
}
/* -------------------< MALLOC SUBSTITUTE >--------------------- */
#ifndef _USE_SMARTHEAP
/*
** Basically, the routines below are dummy routines with the **
** exception of the memory allocation routines which simply **
** allocate memory in the far heap. If you use standard C **
** then you can change the calls to the Microsoft far **
** heap allocators _fmalloc() to the standard malloc() etc. I **
** didn't because I wanted to retain the ability to use the medium **
** model with far data pointers. **
*/
LPVOID PASCAL MemAllocPtr(MEM_POOL pool, WORD wSize,
BOOL bZeroInit)
{
if (bZeroInit)
return (LPVOID)_fcalloc((size_t) wSize, sizeof(char));
else
return (LPVOID)_fmalloc((size_t)wSize);
}
LPVOID PASCAL MemReAllocPtr(LPVOID lpMem, WORD wSize,
BOOL bZeroInit)
{
size_t sizeOld, sizeNew;
LPVOID lpNew;
if (bZeroInit)
{
sizeOld = _fmsize(lpMem);
lpNew = (LPVOID)_frealloc(lpMem, (size_t)wSize);
sizeNew = _fmsize(lpNew);
if ( sizeNew > sizeOld )
{
_fmemset((LPVOID)((LPSTR)lpNew+sizeOld), 0,
(size_t)(sizeNew-sizeOld) );
return lpNew;
}
}
else
return (LPVOID)_frealloc(lpMem, (size_t)wSize);
}
BOOL PASCAL MemFreePtr(LPVOID lpPtr)
{
_ffree(lpPtr);
return TRUE;
}
//
// The following are SMARTHEAP specific routines which here
// are duplicated as dummy routines.
//
MEM_POOL PASCAL MemPoolInit(BOOL bShared)
{
return ((MEM_POOL)NULL);
}
BOOL PASCAL MemPoolFree(MEM_POOL pool)
{
_fheapmin();
return TRUE;
}
DWORD PASCAL MemPoolCount(MEM_POOL pool)
{
return (DWORD)0;
}
BOOL PASCAL MemCheckPtr(MEM_POOL pool, LPVOID lpPtr)
{
// Can't do much here except check to see that the ptr is
// a ptr to a valid XLOPER of type multi
return TRUE; // do nothing
}
BOOL PASCAL MemSetSafetyLevel(int Dum1, BOOL bFlag)
{
return bFlag;
}
#endif // USE_SMARTHEAP
/*----------------------------------------------------------------------*\
Array Utilities
All data is passed back to Excel in an XLOPER of type
xltypeMulti. When using custom functions, this data memory
is released when Excel calls back xlAutoFree(). When using
dialog boxes, the memory is released in the dialog box routine.
It is more convenient to define a xlMulti data structure
whose memory can be deallocated with a single pointer. The
function InitMulti() allocates and initializes this xlMulti
array.
\*----------------------------------------------------------------------*/
/********************************************************************
InitMulti()
=============
This function allocates the XL MULTI array in global memory &
inits the array.
********************************************************************/
LPMULTI PASCAL InitMulti(WORD wRows, WORD wCols, WORD xlType)
{
WORD wSizeData = sizeof(XLOPER)*wRows*wCols;
WORD i;
LPMULTI lpMulti = NULL;
// the array is allocated in one shot which means
// that it can be freed with one pointer. There is no
// need to free the array memory separately
lpMulti = (LPMULTI)MemAllocPtr(gReturnPool,
sizeof(XLOPER)*(wRows*wCols+1), FALSE);
if (lpMulti)
{
// init Multi to call back to xlAutoFree()
lpMulti->Info.xltype = (xltypeMulti | xlbitDLLFree);
// set the array pointer
lpMulti->Info.val.array.lparray = (LPXLOPER)&lpMulti->Data[0];
// set the rows
lpMulti->Info.val.array.rows = wRows;
// set the columns
lpMulti->Info.val.array.columns = wCols;
for (i = 0; i < wRows*wCols; i++)
{
// each XLOPER is initialized to type xlType and zeroed
// note that the memory will be freed with lpMulti.
lpMulti->Data[i].xltype = xlType;
lpMulti->Data[i].val.num = 0.0;
}
}
else
{
ErrorHandler(XLU_NO_MEMORY);
return NULL;
}
return (lpMulti);
}
//
// InitNum() - Init an XLOPER of type Num
//
LPXLOPER PASCAL InitNum(VOID)
{
LPXLOPER lpxlNum = (LPXLOPER)MemAllocPtr(gReturnPool,
sizeof(XLOPER), TRUE);
if (lpxlNum)
{
lpxlNum->xltype = xltypeNum | xlbitDLLFree;
lpxlNum->val.num = 0;
}
else
{
ErrorHandler(XLU_NO_MEMORY);
return NULL;
}
return (lpxlNum);
}
LPXLOPER StripxlbitDLLFree(LPXLOPER lpX)
{
lpX->xltype = lpX->xltype ^ xlbitDLLFree;
return (lpX);
}
/********************************************************************
InitPointers()
=============
This function allocates memory and calculates the pointers for a 2-D
array.
********************************************************************/
LPLPREAL PASCAL InitPointers(LPREAL lpData,
WORD wRows, WORD wCols)
{
WORD id;
LPLPREAL lplpPtrs;
WORD wBytes = sizeof(LPREAL)*wRows;
if ((lplpPtrs= (LPLPREAL)GetMem(wBytes)) == N